package org.ruoyi.aibox.service.impl;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.aibox.domain.AuditTask;
import org.ruoyi.aibox.domain.DocAuditLog;
import org.ruoyi.aibox.domain.DocAuditResult;
import org.ruoyi.aibox.domain.DocAuditResultDetail;
import org.ruoyi.aibox.mapper.AuditTaskMapper;
import org.ruoyi.aibox.mapper.DocAuditLogMapper;
import org.ruoyi.aibox.mapper.DocAuditResultDetailMapper;
import org.ruoyi.aibox.mapper.DocAuditResultMapper;
import org.ruoyi.common.core.exception.ServiceException;
import org.ruoyi.common.core.utils.DateUtils;
import org.ruoyi.common.core.utils.Threads;
import org.ruoyi.common.satoken.utils.LoginHelper;
import org.ruoyi.system.domain.SysFileInfo;
import org.ruoyi.system.mapper.SysFileInfoMapper;
import org.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 文档审核执行器
 */
@Slf4j
@Component
public class DocumentAuditExecutor {

    @Autowired
    private AuditTaskMapper taskMapper;

    @Autowired
    private DocAuditResultMapper resultMapper;

    @Autowired
    private DocAuditResultDetailMapper detailMapper;

    @Autowired
    private DocAuditLogMapper logMapper;

    @Autowired
    private SysFileInfoMapper fileInfoMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private AiModelService aiModelService;

    @Autowired
    private DocumentProcessor documentProcessor;

    @Autowired
    private AuditTaskCounter taskCounter;

    private ThreadPoolExecutor executorService;

    @PostConstruct
    public void init() {
        // 从系统配置获取线程池参数
        int coreSize = Integer.parseInt(configService.selectConfigByKey("sys.audit.pool.coreSize"));
        int maxSize = Integer.parseInt(configService.selectConfigByKey("sys.audit.pool.maxSize"));
        int queueCapacity = Integer.parseInt(configService.selectConfigByKey("sys.audit.pool.queueCapacity"));
        int keepAliveSeconds = Integer.parseInt(configService.selectConfigByKey("sys.audit.pool.keepAliveSeconds"));

        // 创建线程工厂
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
            .setNamePrefix("doc-audit-executor-")
            .build();

        // 创建线程池
        executorService = new ThreadPoolExecutor(
            coreSize,                       // 核心线程数
            maxSize,                        // 最大线程数
            keepAliveSeconds,               // 空闲线程存活时间
            TimeUnit.SECONDS,               // 时间单位
            new LinkedBlockingQueue<>(queueCapacity),  // 工作队列
            threadFactory,                  // 线程工厂
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        log.info("文档审核线程池初始化完成: coreSize={}, maxSize={}, queueCapacity={}, keepAliveSeconds={}",
            coreSize, maxSize, queueCapacity, keepAliveSeconds);
    }

    @PreDestroy
    public void shutdown() {
        Threads.shutdownAndAwaitTermination(executorService);
    }

    /**
     * 检查是否可以接受新任务
     */
    public boolean canAcceptNewTask() {
        return executorService != null
            && !executorService.isShutdown()
            && executorService.getQueue().size() < executorService.getQueue().remainingCapacity();
    }

    /**
     * 执行审核任务
     */
    public void executeAudit(Long taskId) {
        executorService.submit(() -> {
            try {
                // 1. 更新任务状态为进行中
                AuditTask task = new AuditTask();
                task.setTaskId(taskId);
                task.setTaskStatus("1");
                task.setStartTime(new Date());
                task.setUpdateBy(LoginHelper.getUserId());
                task.setUpdateTime(DateUtils.getNowDate());
                taskMapper.updateAuditTask(task);

                // 2. 记录开始日志
                DocAuditLog startLog = new DocAuditLog();
                startLog.setTaskId(taskId);
                startLog.setOperationType("TASK_START");
                startLog.setOperationContent("开始执行审核任务");
                startLog.setCreateBy(LoginHelper.getUserId());
                startLog.setCreateTime(DateUtils.getNowDate());
                startLog.setOperationTime(DateUtils.getNowDate());
                startLog.setStatus("1");
                logMapper.insert(startLog);

                // 3. 获取审核结果记录
                List<DocAuditResult> results = resultMapper.selectByTaskId(taskId);

                // 4. 处理每个审核项
                for (DocAuditResult result : results) {
                    processAuditResult(result);
                }

                // 5. 完成任务
                task = new AuditTask();
                task.setTaskId(taskId);
                task.setTaskStatus("2");
                task.setEndTime(new Date());
                task.setUpdateBy(LoginHelper.getUserId());
                task.setUpdateTime(DateUtils.getNowDate());
                taskMapper.updateAuditTask(task);

                // 6. 记录完成日志
                DocAuditLog completeLog = new DocAuditLog();
                completeLog.setTaskId(taskId);
                completeLog.setOperationType("TASK_COMPLETE");
                completeLog.setOperationContent("审核任务完成");
                completeLog.setCreateBy(LoginHelper.getUserId());
                completeLog.setCreateTime(DateUtils.getNowDate());
                completeLog.setOperationTime(DateUtils.getNowDate());
                completeLog.setStatus("1");
                logMapper.insert(completeLog);

            } catch (Exception e) {
                log.error("任务执行异常", e);

                // 更新任务状态为异常
                AuditTask task = new AuditTask();
                task.setTaskId(taskId);
                task.setTaskStatus("3");
                task.setEndTime(new Date());
                task.setUpdateBy(LoginHelper.getUserId());
                task.setUpdateTime(DateUtils.getNowDate());
                taskMapper.updateAuditTask(task);

                // 记录异常日志
                DocAuditLog errorLog = new DocAuditLog();
                errorLog.setTaskId(taskId);
                errorLog.setOperationType("TASK_ERROR");
                errorLog.setOperationContent("审核任务异常: " + e.getMessage());
                errorLog.setCreateBy(LoginHelper.getUserId());
                errorLog.setCreateTime(DateUtils.getNowDate());
                errorLog.setOperationTime(DateUtils.getNowDate());
                errorLog.setStatus("0");
                logMapper.insert(errorLog);

            } finally {
                // 无论成功还是失败，都需要减少处理中的任务计数
                taskCounter.decrementProcessingCount();
            }
        });
    }

    private void processAuditResult(DocAuditResult result) {
        try {
            // 1. 获取审核项详情
            List<DocAuditResultDetail> details = detailMapper.selectDocAuditResultDetailByResultId(result.getResultId());
            if (details.isEmpty()) {
                log.warn("未找到审核项详情: resultId={}", result.getResultId());
                return;
            }

            // 2. 更新审核状态为处理中
            result.setAuditStatus("1"); // 处理中
            resultMapper.updateDocAuditResult(result);

            // 3. 记录开始日志
            DocAuditLog startLog = new DocAuditLog();
            startLog.setTaskId(result.getTaskId());
            startLog.setOperationType("RESULT_START");
            startLog.setOperationContent("开始处理审核结果");
            startLog.setCreateBy(LoginHelper.getUserId());
            startLog.setCreateTime(DateUtils.getNowDate());
            startLog.setOperationTime(DateUtils.getNowDate());
            startLog.setStatus("1");
            logMapper.insert(startLog);

            // 4. 获取文件信息
            SysFileInfo fileInfo = fileInfoMapper.selectById(result.getDocId());
            if (fileInfo == null) {
                throw new ServiceException("文件不存在：docId=" + result.getDocId());
            }

            // 5. 预处理文档内容
            Map<String, String> chapterMap = documentProcessor.processDocument(fileInfo.getBasePath()+"/"+fileInfo.getUrl());
            if (chapterMap.isEmpty() || !chapterMap.containsKey("全文")) {
                throw new ServiceException("文档处理失败：无法提取内容");
            }

            // 6. 调用AI模型进行审核
            result = aiModelService.auditDocument(result, details, chapterMap);

            // 7. 更新审核结果
            result.setUpdateBy(LoginHelper.getUserId());
            result.setUpdateTime(DateUtils.getNowDate());
            resultMapper.updateDocAuditResult(result);

            // 8. 记录完成日志
            DocAuditLog completeLog = new DocAuditLog();
            completeLog.setTaskId(result.getTaskId());
            completeLog.setOperationType("RESULT_COMPLETE");
            completeLog.setOperationContent("审核结果处理完成");
            completeLog.setCreateBy(LoginHelper.getUserId());
            completeLog.setCreateTime(DateUtils.getNowDate());
            completeLog.setOperationTime(DateUtils.getNowDate());
            completeLog.setStatus("1");
            logMapper.insert(completeLog);

        } catch (Exception e) {
            log.error("处理审核结果异常: resultId={}", result.getResultId(), e);

            // 更新审核状态为异常
            result.setAuditStatus("3"); // 异常
            result.setUpdateBy(LoginHelper.getUserId());
            result.setUpdateTime(DateUtils.getNowDate());
            resultMapper.updateDocAuditResult(result);

            // 记录异常日志
            DocAuditLog errorLog = new DocAuditLog();
            errorLog.setTaskId(result.getTaskId());
            errorLog.setOperationType("RESULT_ERROR");
            errorLog.setOperationContent("处理审核结果异常: " + e.getMessage());
            errorLog.setCreateBy(LoginHelper.getUserId());
            errorLog.setCreateTime(DateUtils.getNowDate());
            errorLog.setOperationTime(DateUtils.getNowDate());
            errorLog.setStatus("1");
            logMapper.insert(errorLog);
        }
    }
}